import axios from 'axios'
// import configuration from 'fisco-bcos/lib/common/configuration'
// import typeCheck from 'fisco-bcos/lib/common/typeCheck'
// import decode from 'fisco-bcos/lib/decoder'
// import web3sync from 'fisco-bcos/lib/common/web3lib/web3sync'
// import utils from 'fisco-bcos/lib/common/web3lib/utils'
import fisco from '../lib/fisco-bcos/lib'
import { ethers } from "ethers";
import { v4 as uuidv4 } from 'uuid';
import Web3 from 'web3'

//封装axios,拦截返回
axios.interceptors.response.use(
  response => {
    if(typeof response.data.error !== "undefined"){
      console.log('axios接口请求失败',response.data.error)
    } else {
      return response;
    }
  },
  error => {
    console.log('axios接口请求失败',error)
  }
);

// 根据实际配置填写
let chainID = 1;
let groupID = 1;
let contractName = "Witness";
// let contractAddress
let contractAddress = "0xed3308688d9a14ad02c23d5eeea6ba53c0d48f86";// FileShare合约部署后的合约地址

let encryptType = fisco.ENCRYPT_TYPE.ECDSA;
// 合约函数的decoder
let decoder;
// abi文件内容填到这里
// const contractAbi = [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"website","type":"string"},{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"services","type":"string"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getDetail","outputs":[{"internalType":"string","name":"detail","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getEmail","outputs":[{"internalType":"string","name":"email","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getName","outputs":[{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getServices","outputs":[{"internalType":"string","name":"services","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getWeb","outputs":[{"internalType":"string","name":"website","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"page","type":"uint256"},{"internalType":"uint256","name":"page_size","type":"uint256"}],"name":"getWitnessList","outputs":[{"internalType":"string","name":"list","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"remove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"string","name":"email","type":"string"}],"name":"setEmail","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"string","name":"services","type":"string"}],"name":"setServices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"string","name":"website","type":"string"}],"name":"setWebsite","outputs":[],"stateMutability":"nonpayable","type":"function"}]
//定义runweb3方法接收两个参数 1.要执行的参数 2.要执行的账户，包括公钥和私钥
function runweb3(param1,myaccount,conparam){
  var that = this
    //2022.7.8重构解构，传入param1为数组
    let inputStr = param1
    const argv = inputStr.split(" ");
    let functionName = argv[0];
    let parameters = argv.slice(1);
    let sendparam = argv.slice(1)
    fisco.typeCheck.check([myaccount.address, contractName, conparam.addr, functionName, parameters],     //conparam.addr 配置
      fisco.typeCheck.Addr, fisco.typeCheck.Str, fisco.typeCheck.Addr, fisco.typeCheck.Str, fisco.typeCheck.ArrayList);
    
    let inputsReg = /\(.*\)/;
    let inputs = inputsReg.exec(functionName);
    if (inputs) {
      inputs = inputs[0];
      inputs = inputs.substring(1, inputs.length - 1).split(',');
      inputs = inputs.map((input) => input.trim());
    }
   
    // 获取abi对象
    let pureFunctionName = functionName.replace(inputsReg, '');
    let abi = getAbi(pureFunctionName, inputs, conparam.abi);
    fisco.typeCheck.check([abi],fisco.typeCheck.Obj);

    // 合约函数的decoder
	  decoder = fisco.decode.createMethodDecoder(abi, null);
    if (abi.stateMutability === "view") {           //只读
    
      //纯读取的方法，用call调用
      let iface = new ethers.utils.Interface(conparam.abi);        //连接合约？
      let abi = iface.functions[pureFunctionName];
      _checkParameters(abi, parameters);      //检查参数
      // 打包交易data
      // console.log('查询前参数',abi)
      let txData = _getTxData(abi, parameters, encryptType);
      let myparam = [
        groupID,
          {
          "from": myaccount.address,
          "to": conparam.addr,      //配置
          "value": "0x0",
          "data": txData
        }
      ]
      return {
        params:myparam,
        type:'view',
        decoder:decoder,
        sendParam:sendparam
      }
    }else{
      /*
      需要上链打包的方法，用sendRawTransaction调用
      */
      let params = parameters;
      
      // 需要先查当前区块高度
      return axios.post(conparam.req, {
        "jsonrpc": "2.0",
        "method": "getBlockNumber",
        "params": [
            groupID,
        ],
        "id": 1
      }).then(res => {
        // 当前区块高度
        let blockNumber = parseInt(res.data.result);
        showResult("执行当前上链之前的区块高度: " + blockNumber);
        // limit
        let blockLimit = parseInt(res.data.result) + 500;
        // 打包交易data
        let txData = _getTxData(abi, params, encryptType);
        // 组装postData
        let postData = {
          data: txData,
          from: myaccount.address,
          to: conparam.addr,      //配置
          gas: 1000000,           //花费
          randomid: _genRandomID(),
          blockLimit: blockLimit,         //块高
          chainId: chainID,
          groupId: groupID,
          extraData: '0x0',
        };
        console.log('组装数据都完成了',postData)
        // 交易签名
        try {
          var signedTx = fisco.web3sync.signTransaction(postData, myaccount.privateKey, encryptType, null);
          // console.log('【交易里看】',(new Web3).eth.accounts)  
          // let aaa = (new Web3).eth.signTransaction({
          //   from: "0xEB014f8c8B418Db6b45774c326A0E64C78914dC0",
          //   gasPrice: "20000000000",
          //   gas: "21000",
          //   to: '0x3535353535353535353535353535353535353535',
          //   value: "1000000000000000000",
          //   data: ""
          // })
          // console.log(aaa)
          // aaa.then((kkk)=>{
          //   console.log('测试的',kkk)
          // })


          // var signedTx = (new Web3).eth.accounts.signTransaction(postData,myaccount.privateKey)
          // return signedTx.then((signedTxd) => { 
          //   console.log('【签完回调】',signedTxd)
          // }).catch((err) => {
          //   console.log('eeeee',err)
          //   // do something when promise fails
            
          // });
          // console.log('签名后',signedTx)
          // signedTx = signedTx.message.data
          // console.log('【简化以后】',signedTx)

        } catch (error) {
          console.log('这里报错了')
          console.log(error)
        }
        // return
        console.log('准备执行交易上链');
        // 交易上链sendRawTransaction
        return axios.post(conparam.req, {
          "jsonrpc": "2.0",
          "method": "sendRawTransaction",
          "params": [
              groupID,
              signedTx
          ],
          "id": 1
        });
      }).then(res => {
        //交易完成
        // 交易hash
        let txHash = res.data.result;
        // 通过hash获取交易回执。可放入具体代码中执行
        console.log('准备执行获取回执');
        return [txHash,decoder]
        // return showTransactionReceipt(txHash,decoder);
      });
    }
}

function getAbi(functionName, inputs,Abi) {
  // console.log('打印我要的')
  // console.log(JSON.parse(contractAbi))
  let contractAbi = JSON.parse(Abi)
  // return
    if (functionName) {
        if (inputs && inputs.length > 0) {
          return contractAbi.find((item) => {
              return item.type === 'function' && item.name === functionName && compareInputs(item.inputs, inputs);
          });
        } else {
          return contractAbi.find((item) => {
            return item.type === 'function' && item.name === functionName;
          });
        }
    }
    return contractAbi;
}

function compareInputs(inputsAbi, inputs){
    if (inputsAbi.length !== inputs.length) {
      return false;
    }
    for (let i = 0; i < inputsAbi.length; ++i) {
			if (inputs[i] !== inputsAbi[i].type) {
					return false;
			}
    }
    return true;
}
function showResult(result){
    console.log('打印结果',result);
    // this.result = this.result + result + "\n\n";
}

function _checkParameters(funct, params) {
    let name = funct.name;
    let inputs = funct.inputs;
    if (inputs.length !== params.length) {
        throw new Error(`wrong number of arguments for \`${name}\`, expected ${inputs.length} but got ${params.length}`);
    }
}
//获取随机id
function _genRandomID() {
    let uuid = uuidv4();
    uuid = uuid.replace(/-/g, '');
    if (!uuid.startsWith('0x')) {
        uuid = '0x' + uuid;
    }
    return uuid;
}
//组合abi参数
function _getTxData(func, params, encryptType) {
  // 计算函数标识 function(type,type,...)
  let inputsTypes = [];
  func.inputs.forEach((v, i) => { inputsTypes.push(v.type); });
  let str = func.name + "(" + inputsTypes.join(",") + ")";
  // 计算摘要（需要支持国密）
  let digest = fisco.hash(str, encryptType);
  // 拼接函数标识
  let txDataCode = '0x' + digest.slice(0, 8);
  // 拼接参数
  let inputs = func.inputs;
  let paramsCode = fisco.web3sync.encodeParams(inputs, params);
  if(paramsCode.slice(0, 2) === '0x'){
      paramsCode = paramsCode.slice(2);
  }
  txDataCode += paramsCode;
  return txDataCode;
}

export {runweb3};